home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Multimedia Toolkit
/
Multimedia Toolkit.iso
/
pascal
/
hardware.pas
< prev
next >
Wrap
Pascal/Delphi Source File
|
1992-11-28
|
7KB
|
234 lines
{****************************************************************************}
{ }
{ MODULE: Hardware }
{ }
{ DESCRIPTION: An UNIT that provides general support to generic Hardware, }
{ like the PIC, the DMA controller, etc... }
{ }
{ AUTHOR: Juan Carlos Arévalo }
{ }
{ MODIFICATIONS: Nobody (yet ;-) }
{ }
{ HISTORY: 18-Nov-1992 Documentation. }
{ }
{ (C) 1992 VangeliSTeam }
{____________________________________________________________________________}
UNIT Hardware;
INTERFACE
PROCEDURE EnableIRQ (i: WORD);
PROCEDURE DisableIRQ (i: WORD);
FUNCTION SetIRQVector(i: WORD; Vec: POINTER) : POINTER;
PROCEDURE DMASet (Channel, Mode: WORD ; Buf: POINTER; Size: WORD);
PROCEDURE DMARawSet(Channel, Mode, Page: BYTE; Offs, Size: WORD);
PROCEDURE DMASetAsm;
IMPLEMENTATION
USES Dos;
{----------------------------------------------------------------------------}
{ PIC routines. }
{____________________________________________________________________________}
PROCEDURE EnableIRQ(i: WORD);
BEGIN
IF i < 8 THEN
PORT[$21] := PORT[$21] AND (NOT (1 SHL i))
ELSE
BEGIN
PORT[$A1] := PORT[$A1] AND (NOT (1 SHL (i-8)));
PORT[$21] := PORT[$21] AND (NOT (1 SHL 2))
END;
END;
PROCEDURE DisableIRQ(i: WORD);
BEGIN
IF i < 8 THEN
PORT[$21] := PORT[$21] OR (1 SHL i)
ELSE
BEGIN
PORT[$A1] := PORT[$A1] OR (1 SHL (i-8))
END;
END;
FUNCTION SetIRQVector(i: WORD; Vec: POINTER) : POINTER;
VAR
p : POINTER;
j : WORD;
BEGIN
IF i < 8 THEN j := i + $08
ELSE j := i + $68;
GetIntVec(j, p);
SetIntVec(j, Vec);
SetIRQVector := p;
END;
{----------------------------------------------------------------------------}
{ DMA routines. }
{____________________________________________________________________________}
{
AH = Channel
CH = Mode
CL = Page
BX = Offset
SI = Size
}
PROCEDURE DMA16Set; ASSEMBLER;
CONST
PageRegTable : ARRAY[0..3] OF WORD = ( $00, $8B, $89, $8A );
ASM
AND AH,3
SHR CL,1
RCR BX,1
ADD CL,CL
MOV AL,AH; ADD AL,$04; OUT $D4,AL { Disable DMA channel. }
XOR AL,AL; OUT $D8,AL { Clear BYTE POINTER flip-flop to lower byte. }
MOV AL,AH; ADD AL,CH; OUT $D6,AL { DMA Mode register. }
XOR DH,DH
MOV DL,AH
ADD DX,DX
ADD DX,DX { Calculate DMA base port. }
ADD DX,$C0
MOV AL,BL; OUT DX,AL { Offset of the buffer, low & high bytes. }
MOV AL,BH; OUT DX,AL
PUSH DX
MOV DL,AH
ADD DX,DX
MOV BX,OFFSET PageRegTable
ADD BX,DX { Calculate page register port. }
MOV DX,[BX]
MOV AL,CL; OUT DX,AL { Set DMA page. }
POP DX
INC DX
INC DX { Calculate DMA counter port. }
MOV BX,SI
MOV AL,BL; OUT DX,AL { Size of the buffer minus 1, low & high byte. }
MOV AL,BH; OUT DX,AL
MOV AL,AH; OUT $D4,AL { Enable DMA channel. }
END;
PROCEDURE DMA8Set; ASSEMBLER;
CONST
PageRegTable : ARRAY[0..3] OF WORD = ( $87, $83, $81, $82 );
ASM
MOV AL,AH; ADD AL,$04; OUT $A,AL { Disable DMA channel. }
XOR AL,AL; OUT $C,AL { Clear BYTE POINTER flip-flop to lower byte. }
MOV AL,AH; ADD AL,CH; OUT $B,AL { DMA Mode register. }
XOR DH,DH
MOV DL,AH
ADD DX,DX { Calculate DMA base port. }
MOV AL,BL; OUT DX,AL { Offset of the buffer, low & high bytes. }
MOV AL,BH; OUT DX,AL
PUSH DX
MOV BX,OFFSET PageRegTable
ADD BX,DX { Calculate page register port. }
MOV DX,[BX]
MOV AL,CL; OUT DX,AL { Set DMA page. }
POP DX
INC DX { Calculate DMA counter port. }
MOV BX,SI
MOV AL,BL; OUT DX,AL { Size of the buffer minus 1, low & high byte. }
MOV AL,BH; OUT DX,AL
MOV AL,AH; OUT $A,AL { Enable DMA channel. }
END;
PROCEDURE DMASetAsm; ASSEMBLER;
ASM
CMP AH,2
JZ @@Fin
CMP AH,4
JZ @@Fin
JB @@8bit
CALL DMA16Set
JMP @@Fin
@@8bit: CALL DMA8Set
@@Fin:
END;
PROCEDURE DMARawSet(Channel, Mode, Page: BYTE; Offs, Size: WORD); ASSEMBLER;
ASM
MOV AH,[Channel]
MOV CH,[Mode]
MOV CL,[Page]
MOV BX,[Offs]
MOV SI,[Size]
CALL DMASetAsm
END;
PROCEDURE DMASet(Channel, Mode: WORD ; Buf: POINTER; Size: WORD);
VAR
Segm : WORD;
Offs : WORD;
BEGIN
Segm := SEG(Buf^) AND $F000;
Offs := SEG(Buf^) AND $0FFF;
IF Offs > 65535 - OFS(Buf^) THEN
BEGIN
INC(Segm, $1000);
Offs := WORD(Offs - 65536 + OFS(Buf^));
END
ELSE
BEGIN
Offs := Offs + OFS(Buf^);
END;
DEC(Size);
DMARawSet(Channel, Mode, Segm SHR 12, Offs, Size);
END;
END.